package ex1;

public class Cell {
	// RELATIVE row and column of threads board
	private int row;
	private int column;
	
	private int generation;
	private boolean currentState;
	// updates from cells in the same generation as this cell
	private int currentStateLiveNeighbors;
	private int currentStateNumOfUpdates;

	// updates from cells in the next generation
	private int nextStateLiveNeighbors;
	private int nextStateNumOfUpdates;

	// Total number of neighbors (not including off board cells)
	private int totalNeighbors;
	

	/**
	 * Cell constructor with numOfliveNeighbors
	 * @param cellRow - RELATIVE cell row of thread board
	 * @param cellColumn - RELATIVE cell column of thread board
	 * @param gen - initial generation
	 * @param state - initial state
	 * @param numOfLiveNeighbors - num of live neighbors
	 * @param totalNeighborsNum -total number of neighbors
	 */
	public Cell(int _row, int _column, int _generation, boolean _currentState, int _currentStateLiveNeighbors, int totalNeighborsNum) {
		row = _row;
		column = _column;
		generation = _generation;
		currentState = _currentState;
		currentStateLiveNeighbors = _currentStateLiveNeighbors;
		currentStateNumOfUpdates = 0;
		nextStateLiveNeighbors = 0;
		nextStateNumOfUpdates = 0;
		totalNeighbors = totalNeighborsNum;
	}

	/**
	 * Get row number (of big board)
	 */
	public int getRow() {
		return row;
	}
	
	/**
	 * Get column number (of big board)
	 */
	public int getColumn() {
		return column;
	}
	
	/**
	 * Get generation
	 */
	public int getGeneration() {
		return generation;
	}

	/**
	 * Set generation
	 * @param gen - the generation to be set
	 */
	public void setGeneration(int _generation) {
		generation = _generation;
	}

	/**
	 * Is alive - returns the current state of the cell
	 */
	public boolean getState() {
		return currentState;
	}

	/**
	 * Go to next state - go to the next generation and set the state by the 'state' param
	 * @param nextState - the new state of the cell
	 */
	public void goToNextState(boolean nextState) {
		generation++;
		currentState = nextState;
		currentStateLiveNeighbors = nextStateLiveNeighbors;
		currentStateNumOfUpdates = nextStateNumOfUpdates;
		nextStateLiveNeighbors = 0;
		nextStateNumOfUpdates = 0;
	}

	/**
	 * Can upgrade, checks if the cell can upgrade
	 * @return true if can upgrade
	 */
	public boolean canUpgrade() {
		return (currentStateNumOfUpdates == totalNeighbors);
	}

	/**
	 * Neighbor update, live or dead changes
	 * @param isAlive - state of a specific neighbor
	 * @return true if can upgrade
	 * */
	public boolean neighborUpdate(boolean isAlive, int updatingCellGeneration) {
		if (updatingCellGeneration == generation) {
			if (isAlive) {
				currentStateLiveNeighbors++; 
			}
			currentStateNumOfUpdates ++;
		} else if (updatingCellGeneration == generation + 1) {
			if (isAlive) {
				nextStateLiveNeighbors++; 
			}
			nextStateNumOfUpdates++;
		}
		return canUpgrade();
	}
	
	/**
	 * upgrade to next state (calculate what it is)
	 * @return next state
	 */
	public void upgrade() {
		boolean nextState;
		
		if ((currentStateLiveNeighbors == 3) || ((currentState) && (currentStateLiveNeighbors == 2))) {
			// if the cell should be alive
			nextState = true;
		} else {
			// else should die
			nextState = false;
		}
		goToNextState(nextState);
	}
}
